package gweb

import (
	"fmt"
	"github.com/beego/beego/v2/core/logs"
	"gorm.io/driver/mysql"
	"reflect"

	//_ "github.com/go-sql-driver/mysql"
	"github.com/spf13/viper"
	"github.com/tidwall/gjson"
	"gorm.io/gorm"
	"gorm.io/gorm/schema"
	"os"
)

func InitDB() {
	enable := viper.GetBool("database.enable")
	if enable {
		dbs := viper.GetStringSlice("database.dbs")
		if dbList == nil {
			dbList = make(map[string]*Db)
		}
		for _, v := range dbs {
			aliasName := gjson.Get(v, "aliasName").String()
			dbType := gjson.Get(v, "type").String()
			dsn := gjson.Get(v, "dsn").String()
			o := NewDB(dbType, dsn)
			dbList[aliasName] = &o
		}
	}
}

// SetGormConfig 设置全局gorm配置
func SetGormConfig(conf gorm.Config) {
	globalGormConfig = conf
	//fmt.Println(globalGormConfig)
}

var (
	dbList           map[string]*Db
	driverList       map[string]func(sqlConn string) gorm.Dialector
	globalGormConfig gorm.Config
)

type Db struct {
	DB *gorm.DB
}

// RegistryDriver 注册驱动
func RegistryDriver(dbType string, cb func(sqlConn string) gorm.Dialector) {
	if driverList == nil {
		driverList = make(map[string]func(sqlConn string) gorm.Dialector)
	}
	driverList[dbType] = cb
	return
}

// NewDB 实例化
func NewDB(dbType, sqlConn string) Db {
	var driver gorm.Dialector
	if _driver, ok := driverList[dbType]; ok {
		driver = _driver(sqlConn)
	} else {
		if dbType == "mysql" {
			driver = mysql.Open(sqlConn)
		} else {
			panic(fmt.Sprintf("driver %s is not support", dbType))
		}
	}
	var cc gorm.Config
	// 如果为空设置默认值
	if reflect.DeepEqual(globalGormConfig, cc) {
		cc = gorm.Config{
			DisableForeignKeyConstraintWhenMigrating: true,
			NamingStrategy: schema.NamingStrategy{
				SingularTable: true, // 使用单数表名，启用该选项，此时，`User` 的表名应该是 `t_user`
			},
		}
	} else {
		cc = globalGormConfig
	}
	db, err := gorm.Open(driver, &cc)
	if err != nil {
		logs.Error("database init error: %s", err)
	}
	return Db{
		DB: db,
	}
}

// GetDB 获取数据库连接
// aliasName 不传默认使用default
func GetDB(aliasName ...string) *gorm.DB {
	_aliasName := "default"
	if len(aliasName) > 0 {
		_aliasName = aliasName[0]
	}
	if _, ok := dbList[_aliasName]; ok {
		return dbList[_aliasName].GetDB()
	} else {
		panic(fmt.Sprintf("db aliasName %s is not registry"))
	}
}
func (__ *Db) GetDB() *gorm.DB {
	if __ == nil {
		logs.Error("db is forgot enable?")
		os.Exit(1)
	}
	return __.DB
}
